#ifndef __M_CONSUMER_H__
#define __M_CONSUMER_H__
#include "../mqcommon/mq_msg.pb.h"
#include "../mqcommon/mq_logger.hpp"
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <sys/types.h>
#include <unordered_map>
#include <vector>
#include <algorithm>


namespace zymq 
{
    using ConsumerCallback = std::function<void(const std::string &tag, const zymq::BasicProperties *bp, const std::string &body)>;
    
    // 消费者
    struct Consumer
    {
        using ptr = std::shared_ptr<Consumer>;
        
        std::string tag;// 消费者标签，用于唯一标识一个消费者
        std::string qname;// 消费者关联的队列名称
        bool auto_ack;// 是否自动确认消息
        ConsumerCallback callback; // 当有消息到达时的回调函数，作用是将消息发送给订阅者

        Consumer(){}
        Consumer(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallback &cb)
            :tag(ctag), qname(queue_name), auto_ack(ack_flag), callback(cb) {}
    };

    // 队列消费者
    class QueueConsumer
    {
    public:
        using ptr = std::shared_ptr<QueueConsumer>;

        QueueConsumer(const std::string &qname) : _qname(qname), _rr_seq(0) {}

        Consumer::ptr create(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallback &cb)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            
            // 检查消费者是否已存在
            for (const auto &consumer : _consumers) {
                if (consumer->tag == ctag) {
                    DLOG("消费者 %s 已存在", ctag.c_str());
                    return nullptr;
                }
            }
            
            // 创建新的消费者
            Consumer::ptr consumer = std::make_shared<Consumer>(ctag, queue_name, ack_flag, cb);
            _consumers.push_back(consumer);
            
            return consumer;
        }

        void remove(const std::string &ctag)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 这里的 const Consumer::ptr &consumer 其实不是“迭代器赋值过来”的意思，而是在 std::find_if 算法遍历容器时，
            // 依次把容器中的元素（即 Consumer::ptr 对象）传递给 Lambda 表达式的这个参数。
            // std::find_if(容器.begin(), 容器.end(), [](const Consumer::ptr &consumer){ ... }) 的写法中，
            // Lambda 参数 consumer 就是容器里的每一个元素的引用。
            // 换句话说，std::find_if 在遍历时，会依次把 _consumers 里的每个 Consumer::ptr 取出来，传给 Lambda 里的 consumer 形参。
            // 如果 Lambda 返回 true，find_if 就会停止查找并返回对应元素的迭代器。
            auto it = std::find_if(_consumers.begin(), _consumers.end(),
                [&ctag](const Consumer::ptr &consumer) {
                    return consumer->tag == ctag;
                });
            
            if (it != _consumers.end()) {
                _consumers.erase(it);
            }
        }

        Consumer::ptr choose()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            
            if (_consumers.empty()) {
                return nullptr;
            }
            
            // 使用轮询算法选择消费者
            size_t index = _rr_seq % _consumers.size();
            
            // 更新轮询序列号
            _rr_seq++;
            
            return _consumers[index];
        }

        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _consumers.empty();
        }

        bool exists(const std::string &ctag)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            
            auto it = std::find_if(_consumers.begin(), _consumers.end(),
                [&ctag](const Consumer::ptr &consumer) {
                    return consumer->tag == ctag;
                });
            
            return it != _consumers.end();
        }

        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            
            _consumers.clear();
            _rr_seq = 0;
        }

    private:
        std::string _qname; // 队列名称
        std::mutex _mutex;// 保护_consumers线程安全
        uint64_t _rr_seq; // 轮转序号
        std::vector<Consumer::ptr> _consumers; // 该队列所关联的所有消费者
    };

    class ConsumerManager
    {
    public:
        using ptr = std::shared_ptr<ConsumerManager>;

        ConsumerManager(){}

        void initQueueConsumer(const std::string &qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            
            auto it = _consumers.find(qname);
            if (it == _consumers.end()) {
                QueueConsumer::ptr qc = std::make_shared<QueueConsumer>(qname);
                _consumers[qname] = qc;
                DLOG("消费者管理器为队列 %s 创建新的消费者管理器", qname.c_str());
            }
        }

        void destroyQueueConsumer(const std::string &qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            
            auto it = _consumers.find(qname);
            if (it != _consumers.end()) {
                _consumers.erase(it);
                DLOG("消费者管理器删除队列 %s 的消费者管理器", qname.c_str());
            }
        }

        Consumer::ptr create(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallback &cb)
        {
            QueueConsumer::ptr qc;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                
                // 查找队列消费者管理器
                auto it = _consumers.find(queue_name);
                if (it == _consumers.end()) {
                    DLOG("队列 %s 不存在消费者管理器", queue_name.c_str());
                    return nullptr;
                }
                
                qc = it->second;  // 获取QueueConsumer的智能指针
            }  // 释放ConsumerManager的锁
            
            // 在ConsumerManager锁外调用QueueConsumer的create，避免锁中锁
            Consumer::ptr consumer = qc->create(ctag, queue_name, ack_flag, cb);
            if (consumer) {
                DLOG("消费者管理器成功创建消费者: %s -> %s", ctag.c_str(), queue_name.c_str());
            }
            
            return consumer;
        }

        void remove(const std::string &ctag, const std::string &queue_name)
        {
            QueueConsumer::ptr qc;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                
                auto it = _consumers.find(queue_name);
                if (it == _consumers.end()) {
                    DLOG("队列 %s 不存在消费者管理器", queue_name.c_str());
                    return;
                }
                
                qc = it->second;  // 获取QueueConsumer的智能指针
            }  // 释放ConsumerManager的锁
            
            // 在ConsumerManager锁外调用QueueConsumer的remove，避免锁中锁
            qc->remove(ctag);
            DLOG("消费者管理器移除消费者: %s -> %s", ctag.c_str(), queue_name.c_str());
        }

        Consumer::ptr choose(const std::string &queue_name)
        {
            QueueConsumer::ptr qc;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                
                auto it = _consumers.find(queue_name);
                if (it == _consumers.end()) {
                    DLOG("队列 %s 不存在消费者管理器", queue_name.c_str());
                    return nullptr;
                }
                
                qc = it->second;  // 获取QueueConsumer的智能指针
            }  // 释放ConsumerManager的锁
            
            // 在ConsumerManager锁外调用QueueConsumer的choose，避免锁中锁
            Consumer::ptr consumer = qc->choose();
            if (consumer) {
                DLOG("消费者管理器为队列 %s 选择消费者: %s", queue_name.c_str(), consumer->tag.c_str());
            }
            
            return consumer;
        }

        bool empty(const std::string &queue_name)
        {
            QueueConsumer::ptr qc;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                
                auto it = _consumers.find(queue_name);
                if (it == _consumers.end()) {
                    return true;
                }
                
                qc = it->second;  // 获取QueueConsumer的智能指针
            }  // 释放ConsumerManager的锁
            
            // 在ConsumerManager锁外调用QueueConsumer的empty，避免锁中锁
            return qc->empty();
        }

        bool exists(const std::string &ctag, const std::string &queue_name)
        {
            QueueConsumer::ptr qc;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                
                auto it = _consumers.find(queue_name);
                if (it == _consumers.end()) {
                    return false;
                }
                
                qc = it->second;  // 获取QueueConsumer的智能指针
            }  // 释放ConsumerManager的锁
            
            // 在ConsumerManager锁外调用QueueConsumer的exists，避免锁中锁
            return qc->exists(ctag);
        }

        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _consumers.clear();
        }

    private:
        std::mutex _mutex;
        std::unordered_map<std::string, QueueConsumer::ptr> _consumers;

    };
}

#endif